﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Security.Cryptography;
using System.Diagnostics;
using System.Reflection;
using WebLibraryMaker.Properties;

namespace WebLibraryMaker
{
    class Program
    {
        /// <summary>
        /// The tool converts given WebApplication to user controls library.
        /// It does following steps
        /// 1) depending of hash of the Dll: backup unchanged Dll OR restore it before processing (in order to prevent double processing of the same file)
        /// 2) call aspnet_compiler
        /// 3) gather names of newly created Dlls
        /// 4) create "interface" Dll containing classes inherited from ASP.XX ones. These classes have names similiar to grandparents' ones.
        /// 5) load special unmanaged resources from Dlls created by aspnet_compiler
        /// 6) merge all these Dlls into one file (interface Dll + Dlls created by aspnet_compiler + initial Dll) using ILMerge tool
        /// 7) write special unmanaged resource into resulting Dll
        /// 8) overwrite Dll files within output and intermediate folders
        /// 9) calculate hash code of the Dll 
        /// </summary>
        /// <param name="args">        
        /// the appliaction supports following parameters:
        /// /net [installation directory of .NET 2.0] 
        /// /name [name of the assembly] 
        /// /prj [full path of the project directory] 
        /// /obj [relative path of the intermediate directory] 
        /// /out [relative path of the output directory] 
        /// /debug [true|false]
        /// /key [name of key file]
        /// /ds [true|false]  (= delaySign)
        /// all parameters are required
        /// you can use something like "$(MSBuildProjectDirectory)\..\WebLibraryMaker\WebLibraryMaker.exe" /net " $(Framework20Dir) " /name " $(MSBuildProjectName) " /prj " $(MSBuildProjectDirectory) " /obj " $(IntermediateOutputPath) " /out " $(OutDir) " /debug $(DebugSymbols)
        /// </param>
        /// <returns>
        /// 0 in case of successful processing
        /// error code in case of error
        /// </returns>
        static int Main(string[] args)
        {
            try
            {
                //there are a lot of different pathes to process
                //I've stored them into a nice container
                Pathes pathes = new Pathes();
                bool debug;
                bool delaySign;

                // first of all - to parse command line parameters
                ArgumentParser.ParseArgs(args, pathes, out debug, out delaySign);
                // compare hashes; create/restore backups
                Backup.CheckBackup(pathes);

                //precompile the application
                int compileResult = AspnetCompiler.PrecompileWebApplication(pathes, debug);
                if (compileResult != 0) return compileResult;

                //gather newly created Dll files
                List<string> aspCompiledPathes = new List<string>(Directory.GetFiles(pathes.CompiledDirectory, "App_Web_*.dll"));
                if (aspCompiledPathes.Count == 0) return 0;
                //insert initial Dll into the collection
                aspCompiledPathes.Insert(0, pathes.CompiledFile); 

                //build interface library
                string interfaceAsm = InterfaceBuilder.Build(pathes, aspCompiledPathes.ToArray());

                if (interfaceAsm != null)
                {
                    //load special unmamaged resources
                    byte[] resource = Resources.LoadResources(aspCompiledPathes.ToArray());
                    aspCompiledPathes.Insert(0, interfaceAsm);
                    //merge all Dlls
                    Merge.DoMerge(pathes.OutputDll, pathes.CompiledFile, aspCompiledPathes.ToArray(), pathes.KeyFileBillet, delaySign);
                    //insert special unmanaged resource into resulting Dll
                    if (resource != null) Resources.InsertResources(pathes.OutputDll, resource);

                    //calculate hash code, copy result into intermediate Dll
                    Backup.CreateBackup(pathes);                    
                }
                else
                {
                    throw new Exception("No interface library created");
                }
            }
            catch (Exception ex)
            {
                Console.Write(ex.ToString());
                return 1;
            }

            return 0;
        }
    }
}
